package cn.psvmc.cxzapi.service.order;

import cn.psvmc.cxzapi.mapper.customer.TCustomerCouponMapper;
import cn.psvmc.cxzapi.mapper.goods.TGoodsSpecsMapper;
import cn.psvmc.cxzapi.mapper.order.*;
import cn.psvmc.cxzapi.model.common.OrderTaskEntity;
import cn.psvmc.cxzapi.model.goods.TGoodsSpecs;
import cn.psvmc.cxzapi.model.order.*;
import cn.psvmc.cxzapi.service.alipay.AlipayCreate;
import cn.psvmc.cxzapi.service.system.ServiceUtil;
import cn.psvmc.cxzapi.util.ToolUtils;
import com.alipay.api.domain.GoodsDetail;
import com.alipay.api.response.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

/**
 * @author ywx
 * @className TOrderTaskService
 * @description 订单定时任务服务
 * @date 2024/9/28 20:51
 **/
@Service
@Slf4j
public class TOrderTaskService {
    @Resource
    private TOrderTaskMapper orderTaskMapper;
    @Resource
    private ServiceUtil serviceUtil;
    @Resource
    private TOrderMapper orderMapper;
    @Resource
    private TGoodsSpecsMapper goodsSpecsMapper;
    @Resource
    private TOrderCouponMapper tOrderCouponMapper;
    @Resource
    private TCustomerCouponMapper tCustomerCouponMapper;
    @Resource
    private TOrderBillMapper tOrderBillMapper;
    @Resource
    private TOrderLogService orderLogService;

    /**
     * @Description 定时支付宝生成交易号
     * @Date 2024/9/28 22:55
     * @Author YWX
     * @Param []
     * @Return void
     **/
    public void generateTradeNo() {
        Date now = new Date();
        List<TOrderBill> bills = orderTaskMapper.listNotTradeNo(now);
        if (ToolUtils.isListEmpty(bills)) return;
        for (TOrderBill bill : bills) {
            updateTradeNo(bill);//更新支付宝交易号
        }
    }

    //更新支付宝交易号
    @Async("asyncPoolTaskExecutor")
    public void updateTradeNo(TOrderBill bill) {
        try {
            GoodsDetail gd = orderMapper.getGoodsDetail(bill.getOrderId());
            String tradeNo = serviceUtil.getTradeNo(bill.getTransactionId(), bill.getPayAmount(), bill.getComm(), bill.getBody(), bill.getCreateid(), gd);
            bill.setTradeNo(tradeNo);
        } catch (Exception e) {
            log.error("更新支付宝交易号失败，订单号：{}，异常信息：{}", bill.getTransactionId(), e.getMessage());
        } finally {
            bill.setIsGenerate(1);
            orderTaskMapper.updateById(bill);
        }
    }

    /**
     * @Description 更新待归还订单状态
     * @Date 2024/9/28 23:14
     * @Author YWX
     * @Param []
     * @Return void
     **/
    public void updateOrderStatus() {
        Date now = new Date();
        orderTaskMapper.updateOrderStatus(now);
    }

    /**
     * @Description 定时取消订单
     * @Date 2024/10/27 20:50
     * @Author YWX
     * @Param []
     * @Return void
     **/
    public void cancelOrder() {
        LocalDateTime time = LocalDateTime.now().minusMinutes(30);
        List<OrderTaskEntity> tasks = orderTaskMapper.listCancelOrderIds(time);
        if (ToolUtils.isListEmpty(tasks)) return;
        for (OrderTaskEntity task : tasks) {
            Integer gsid = task.getGsid();
            Integer orderId = task.getOrderId();
            List<TOrderBill> bills = orderTaskMapper.listByOrderId(orderId);
            for (TOrderBill bill : bills) {
                serviceUtil.closeBill(bill.getObid(), bill.getTransactionId());
            }
            //更新订单状态
            TOrder tOrder = new TOrder();
            tOrder.setOrderId(orderId);
            tOrder.setOrderStatus(7);
            tOrder.setControlComm("订单超时自动取消");
            orderMapper.taskUpdateOrderStatus(tOrder);
            TGoodsSpecs specs = goodsSpecsMapper.selectById(gsid);
            Integer stock = specs.getStock();
            int outStock = 0;
            if (stock.equals(task.getNum())) {//购买数量等于库存，标记缺货
                outStock = 1;
            }
            specs.setOutStock(outStock);
            specs.setStock(task.getNum());
            goodsSpecsMapper.uodateStock(specs);//更新库存

            cancelCoupon(orderId, task.getCustomerid());//取消订单的优惠券
        }
    }

    /**
     * @Description 取消订单的优惠券
     * @Date 2024/11/20 22:55
     * @Author YWX
     * @Param [orderId, customerid]
     * @Return void
     **/
    @Async("asyncPoolTaskExecutor")
    public void cancelCoupon(Integer orderId, Integer customerid) {
        serviceUtil.refundCoupon(orderId, customerid);
    }

    /**
     * @Description 账单代扣定时任务
     * @Date 2024/11/30 20:52
     * @Author YWX
     * @Param []
     * @Return void
     **/
    public void tradePay() {
        List<TOrderBill> bills = orderTaskMapper.listTradePay(LocalDate.now());//获取需要代扣的账单列表
        if (ToolUtils.isListEmpty(bills)) return;
        for (TOrderBill bill : bills) {
            Integer obid = bill.getObid();
            String transactionId = bill.getTransactionId();
            Double payAmount = bill.getPayAmount();
            String orderCode = bill.getOrderCode();
            String authNo = bill.getAuthNo();
            /*if (ToolUtils.isEmpty(authNo)) {
                AlipayFundAuthOperationDetailQueryResponse response = AlipayCreate.alipayFundAuthOperationDetailQuery(orderCode);//资金授权操作查询
                if (response.isSuccess()) {
                    authNo = response.getAuthNo();
                } else {
                    //添加操作日志
                    TOrderLog log = new TOrderLog();
                    log.setOrderCode(orderCode);
                    log.setComm("定时任务账单代扣失败，第" + bill.getPeriod() + "期,支付金额：" + payAmount + "元");
                    log.setLogType("冻结押金转支付");
                    tOrderLogMapper.save(log);
                }
            }*/
            if (ToolUtils.isNotEmpty(authNo)) {
                int num = 1;
                tradePay(bill, authNo, num);
            }
        }
    }

    //账单代扣
    @Async("asyncPoolTaskExecutor")
    public void tradePay(TOrderBill bill, String authNo, int num) {
        Integer obid = bill.getObid();
        String transactionId = bill.getTransactionId();
        Double payAmount = bill.getPayAmount();
        String orderCode = bill.getOrderCode();
        String installmentOrderId = bill.getInstallmentOrderId();
        if (ToolUtils.isEmpty(installmentOrderId) && bill.getConfirmed().equals(1)) {
            AlipayOpenMiniOrderInstallmentCreateResponse createResponse = AlipayCreate.orderInstallmentCreate(bill, bill.getOpenid(), "RENT", false);
            installmentOrderId = createResponse.getInstallmentOrderId();
        }
        AlipayTradePayResponse response1 = AlipayCreate.alipayTradePay3(transactionId, authNo, "押金转支付", bill.getBody(), payAmount, installmentOrderId, bill.getTradeComponentOrderId(), orderMapper.getGoodsDetail(bill.getOrderId()));
        TOrderBill bill1 = new TOrderBill();
        bill1.setInstallmentOrderId(installmentOrderId);
        bill1.setObid(obid);
        boolean flag = false;//是否成功
        if (response1.isSuccess() || response1.getSubMsg().equals("交易已经支付")) {
            Date gmtPayment = response1.getGmtPayment();//付款时间
            // 转换为LocalDateTime
            LocalDateTime localDateTime = ToolUtils.dateToLocalDateTime(gmtPayment);
            bill1.setRealDate(localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            bill1.setPayTime(localDateTime);
            bill1.setCutTime(localDateTime);
            bill1.setTradeStatus(1);
            bill1.setBillStatus(1);
            bill1.setAvailableAmount(payAmount);
            bill1.setPayType(2);
            if (bill.getBillStatus().equals(0)) {
                serviceUtil.addAccountBillByTradeNo(transactionId, 1, 31);
            }
            flag = true;
        }
        tOrderBillMapper.updateByIdForService(bill1);//服务端扣款更新账单状态
        if (!flag && num < 5) {
            num++;
            //根据num重试tradePay：num=2间隔1h重试、num=3间隔2h重试、num=4间隔6h重试、num=5间隔12h重试
            // 根据num设置不同的重试间隔
            long sleepTime = switch (num) {
                case 2 -> 60 * 60 * 1000; // 1小时
                case 3 -> 2 * 60 * 60 * 1000; // 2小时
                case 4 -> 6 * 60 * 60 * 1000; // 6小时
                case 5 -> 12 * 60 * 60 * 1000; // 12小时
                default -> throw new IllegalArgumentException("Unexpected value: " + num);
            };

            try {
                Thread.sleep(sleepTime); // 等待指定的时间
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 恢复中断状态
            }
            tradePay(bill, authNo, num);
        }
        TOrderLog log = new TOrderLog();
        log.setOrderCode(orderCode);
        String result;
        if (flag) {
            updateRestAmountByCode(orderCode, payAmount);//更新订单剩余冻结金额
            result = "成功";
        } else {
            result = "失败";
        }
        log.setComm("定时任务账单代扣" + result + "，第" + bill.getPeriod() + "期,支付金额：" + payAmount + "元");
        log.setLogType("冻结押金转支付");
        orderLogService.saveOrderLog(log);
    }

    //更新订单剩余冻结金额
    private void updateRestAmountByCode(String orderCode, Double restAmount) {
        AlipayFundAuthOperationDetailQueryResponse response = AlipayCreate.alipayFundAuthOperationDetailQuery(orderCode);//资金授权操作查询
        if (response.isSuccess()) {
            String restAmount1 = response.getRestAmount();
            if (restAmount.compareTo(ToolUtils.objToDouble(restAmount1)) != 0) {
                TOrder order = new TOrder();
                order.setOrderCode(orderCode);
                order.setRestAmount(ToolUtils.objToDouble(restAmount1));
                orderMapper.updateRestAmountByCode(order);
            }
        }
    }
}
